home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 March / Macworld (1998-03) (Disk 1).dmg / Shareware World / Info / For Developers / GhostScript 5.10 / MacGS-510 / files / wrfont.ps < prev    next >
Text File  |  1996-07-03  |  18KB  |  664 lines

  1. %    Copyright (C) 1991, 1995, 1996 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of Aladdin Ghostscript.
  3. % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  4. % or distributor accepts any responsibility for the consequences of using it,
  5. % or for whether it serves any particular purpose or works at all, unless he
  6. % or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  7. % License (the "License") for full details.
  8. % Every copy of Aladdin Ghostscript must include a copy of the License,
  9. % normally in a plain ASCII text file named PUBLIC.  The License grants you
  10. % the right to copy, modify and redistribute Aladdin Ghostscript, but only
  11. % under certain conditions described in the License.  Among other things, the
  12. % License requires that the copyright notice and this notice be preserved on
  13. % all copies.
  14.  
  15. % wrfont.ps
  16. % Write out a Type 1 font in readable, reloadable form.
  17. % Note that this does NOT work on protected fonts, such as Adobe fonts
  18. % (unless you have loaded unprot.ps first, in which case you may be
  19. % violating the Adobe license).
  20.  
  21. % ****** NOTE: This file must be kept consistent with gs_pfile.ps.
  22.  
  23. /wrfont_dict 100 dict def
  24. wrfont_dict begin
  25.  
  26. % ------ Options ------ %
  27.  
  28. % Define whether to use eexec encryption for the font.
  29. % eexec encryption is only useful for compatibility with Adobe Type Manager
  30. % and other programs; it only slows Ghostscript down.
  31.    /eexec_encrypt false def
  32.  
  33. % Define whether to write out the CharStrings in binary or in hex.
  34. % Binary takes less space on the file, but isn't guaranteed portable.
  35.    /binary_CharStrings false def
  36.  
  37. % Define whether to use binary token encodings when possible.
  38. % Binary tokens are smaller and load faster, but are a Level 2 feature.
  39.    /binary_tokens false def
  40.  
  41. % Define whether to encrypt the CharStrings on the file.  (CharStrings
  42. % are always encrypted in memory.)  Unencrypted CharStrings load about
  43. % 20% slower, but make the files compress much better for transport.
  44.    /encrypt_CharStrings true def
  45.  
  46. % Define whether the font must provide standard PostScript language
  47. % equivalents for any facilities it uses that are provided in Ghostscript
  48. % but are not part of the standard PostScript language.
  49.    /standard_only true def
  50.  
  51. % Define the value of lenIV to use in writing out the font.
  52. % use_lenIV = 0 produces the smallest output, but this may not be
  53. % compatible with old Adobe interpreters.  use_lenIV = -1 means
  54. % use the value of lenIV from the font.
  55.    /use_lenIV -1 def
  56.  
  57. % Define whether to produce the smallest possible output, relying
  58. % as much as possible on Ghostscript-specific support code.
  59. % Taking full advantage of this requires the following settings:
  60. % binary_CharStrings = true, binary_tokens = true, standard_only = false.
  61.    /smallest_output false def
  62.  
  63. % Define whether to write out all currently known Encodings by name,
  64. % or only StandardEncoding and ISOLatin1Encoding.
  65.    /name_all_Encodings false def
  66.  
  67. % ---------------- Runtime support ---------------- %
  68.  
  69. /.packedfilefilter where
  70.  { pop }
  71.  { (gs_pfile.ps) runlibfile }
  72. ifelse
  73.  
  74. % ------ Output utilities ------ %
  75.  
  76. % By convention, the output file is named psfile.
  77.  
  78. % Define some utilities for writing the output file.
  79.    /wtstring 2000 string def
  80.    /wb {psfile exch write} bind def
  81.    /wnb {/wb load repeat} bind def
  82.    /w1 {psfile exch write} bind def
  83.    /ws {psfile exch writestring} bind def
  84.    /wl {ws (\n) ws} bind def
  85.    /wt {wtstring cvs ws ( ) ws} bind def
  86.    /wd        % Write a dictionary.
  87.     { dup length wo {dict dup begin} wol { we } forall
  88.       {end} wol
  89.     } bind def
  90.    /wld        % Write a large dictionary more efficiently.
  91.            % Ignore the readonly attributes.
  92.     { dup length wo {dict dup begin} wol
  93.       0 exch
  94.        { exch wo wo () wl
  95.      1 add dup 200 eq
  96.       { wo ({def} repeat) wl 0 }
  97.      if
  98.        }
  99.       forall
  100.       dup 0 ne
  101.        { wo ({def} repeat) wl }
  102.        { pop }
  103.       ifelse
  104.       (end) ws
  105.     } bind def
  106.    /we        % Write a dictionary entry.
  107.     { exch wo wo /def cvx wo (\n) ws
  108.     } bind def
  109.    /wcs        % Write a CharString (or Subrs entry)
  110.     { dup type /stringtype eq
  111.        { 4330 exch changelenIV 0 ge
  112.           {    % Add some leading garbage bytes.
  113.         wtstring changelenIV 2 index length getinterval
  114.         .type1decrypt exch pop
  115.         wtstring exch 0 exch length changelenIV add getinterval
  116.       }
  117.       {    % Drop some leading garbage bytes.
  118.         wtstring .type1decrypt exch pop
  119.         changelenIV neg 1 index length 1 index sub getinterval
  120.       }
  121.      ifelse
  122.          binary_tokens encrypt_CharStrings and
  123.       { % Suppress recognizing the readonly status of the string.
  124.         4330 exch dup .type1encrypt exch pop wo
  125.       }
  126.       { encrypt_CharStrings
  127.          { 4330 exch dup .type1encrypt exch pop
  128.          } if
  129.         smallest_output
  130.          { wo
  131.          }
  132.          { readonly dup length wo
  133.            binary_tokens not { ( ) ws } if
  134.            readproc ws wx
  135.          }
  136.         ifelse
  137.       }
  138.      ifelse
  139.        }
  140.        { wo        % PostScript procedure
  141.        }
  142.       ifelse
  143.     } bind def
  144.  
  145. % Construct the inversion of the system name table.
  146.    /SystemNames where
  147.     { pop /snit 256 dict def
  148.       0 1 255
  149.        { dup SystemNames exch get
  150.          dup null ne { exch snit 3 1 roll put } { pop pop } ifelse
  151.        }
  152.       for
  153.     }
  154.     { /snit 1 dict def
  155.     }
  156.    ifelse
  157.  
  158. % Write an object, using binary tokens if requested and possible.
  159.    /woa        % write in ascii
  160.     { psfile exch write==only
  161.     } bind def
  162.  
  163.             % Lookup table for ASCII output.
  164.  
  165.    /intbytes    % int nbytes -> byte*
  166.     { { dup 255 and exch -8 bitshift } repeat pop
  167.     } bind def
  168.    /wotta 10 dict dup begin
  169.       { /booleantype /integertype }
  170.       { { ( ) ws woa } def }
  171.      forall
  172.         % Iterate over arrays so we can print operators.
  173.      /arraytype
  174.       { dup xcheck {(}) ({)} {(]) ([)} ifelse ws exch dup wol exch ws wop
  175.       } bind def
  176.      /dicttype
  177.       { ( ) ws wd } def
  178.      /nametype
  179.       { dup xcheck { ( ) ws } if woa
  180.       } bind def
  181.         % Map back operators to their names,
  182.         % so we can write procedures.
  183.      /nulltype
  184.       { pop ( null) ws
  185.       } bind def
  186.      /operatortype
  187.       { wtstring cvs cvn cvx wo
  188.       } bind def
  189.         % Convert reals to integers if possible.
  190.      /realtype
  191.       { dup cvi 1 index eq { cvi wo } { ( ) ws woa } ifelse
  192.       } bind def
  193.         % == truncates strings longer than 200 characters!
  194.      /stringtype
  195.       { (\() ws dup
  196.      { dup dup 32 lt exch 127 ge or
  197.         { (\\) ws dup -6 bitshift 48 add w1
  198.           dup -3 bitshift 7 and 48 add w1
  199.           7 and 48 add
  200.         }
  201.         { dup dup -2 and 40 eq exch 92 eq or {(\\) ws} if
  202.         }
  203.        ifelse w1
  204.      }
  205.     forall
  206.     (\)) ws wop
  207.       } bind def
  208.      /packedarraytype
  209.       { ([) ws dup { wo } forall
  210.     encodingnames 1 index known
  211.         % This is an encoding, but not one of the standard ones.
  212.         % Use the built-in encoding only if it is available.
  213.      { encodingnames exch get wo
  214.        ({findencoding}stopped{pop) ws
  215.        (}{counttomark 1 add 1 roll cleartomark}ifelse)
  216.      }
  217.      { pop ()
  218.      }
  219.     ifelse
  220.     (/packedarray where{pop counttomark packedarray exch pop}{]readonly}ifelse) ws
  221.     wl
  222.       }
  223.      def
  224.    end def
  225.  
  226.             % Lookup table for binary output.
  227.  
  228.    /wottb 8 dict dup begin
  229.    wotta currentdict copy pop
  230.      /integertype
  231.       { dup dup 127 le exch -128 ge and
  232.          { 136 wb 255 and wb }
  233.      { dup dup 32767 le exch -32768 ge and
  234.         { 134 wb 2 intbytes wb wb }
  235.         { 132 wb 4 intbytes wb wb wb wb }
  236.        ifelse
  237.      }
  238.     ifelse
  239.       } bind def
  240.      /nametype
  241.       { dup snit exch known
  242.          { dup xcheck { 146 } { 145 } ifelse wb
  243.        snit exch get wb
  244.      }
  245.      { wotta /nametype get exec
  246.      }
  247.     ifelse
  248.       } bind def
  249.      /stringtype
  250.       { dup dup length dup 255 le { 142 2 } { 2 intbytes 143 3 } ifelse wnb
  251.     ws wop
  252.       } bind def
  253.    end def
  254.  
  255.    /wop        % Write object protection
  256.      { wcheck not { /readonly cvx wo } if
  257.      } bind def
  258.    /wo        % Write an object.
  259.      { dup type binary_tokens { wottb } { wotta } ifelse
  260.        exch get exec
  261.      } bind def
  262.    /wol        % Write a list of objects.
  263.      { { wo } forall
  264.      } bind def
  265.  
  266. % Write a hex string for Subrs or CharStrings.
  267.    /wx        % string ->
  268.     { binary_CharStrings
  269.        { ws
  270.        }
  271.        { % Some systems choke on very long lines, so
  272.      % we break up the hexstring into chunks of 50 characters.
  273.       { dup length 25 le {exit} if
  274.         dup 0 25 getinterval psfile exch writehexstring (\n) ws
  275.         dup length 25 sub 25 exch getinterval
  276.       } loop
  277.      psfile exch writehexstring
  278.        } ifelse
  279.     } bind def
  280.  
  281. % ------ CharString encryption utilities ------ %
  282.  
  283. /enc_dict 20 dict def
  284. 1 dict begin
  285. /bind { } def        % make sure we can print out the procedures
  286. enc_dict begin
  287.  
  288. (type1enc.ps) runlibfile
  289. enc_dict /.type1decrypt undef        % we don't need this
  290.  
  291. end end
  292.  
  293. enc_dict { 1 index where { pop pop pop } { def } ifelse } forall
  294.  
  295. % ------ Other utilities ------ %
  296.  
  297. % Test whether two values are equal (for default dictionary entries).
  298.    /valueeq        % <obj1> <obj2> valueeq <bool>
  299.     { 2 copy eq
  300.        { pop pop true }
  301.        {    % Special hack for comparing FontMatrix values
  302.      dup type /arraytype eq 2 index type /arraytype eq and
  303.       { dup length 2 index length eq
  304.          { true 0 1 3 index length 1 sub
  305.         {    % Stack: arr1 arr2 true index
  306.           3 index 1 index get 3 index 3 -1 roll get eq not
  307.            { pop false exit }
  308.           if
  309.         }
  310.            for 3 1 roll pop pop
  311.          }
  312.          { pop pop false
  313.          }
  314.         ifelse
  315.       }
  316.       { pop pop false
  317.       }
  318.      ifelse
  319.        }
  320.       ifelse
  321.     } bind def
  322.  
  323. % ------ The main program ------ %
  324.  
  325. % Define the dictionary of keys to skip because they are treated specially.
  326. /.fontskipkeys mark
  327.   /CharStrings dup
  328.   /Encoding dup
  329.   /FDepVector dup
  330.   /FID dup
  331.   /FontInfo dup
  332.   /Metrics dup
  333.   /Metrics2 dup
  334.   /Private dup
  335. .dicttomark def
  336. /.minfontskipkeys mark
  337.   .fontskipkeys { } forall
  338.   /FontName dup
  339.   /UniqueID dup
  340. .dicttomark def
  341. /.privateskipkeys mark
  342.   /ND dup
  343.   /NP dup
  344.   /RD dup
  345.   /Subrs dup
  346. .dicttomark def
  347. /.minprivateskipkeys mark
  348.   .privateskipkeys { } forall
  349.   /MinFeature dup
  350.   /Password dup
  351.   /UniqueID dup
  352. .dicttomark def
  353.  
  354. % Define the procedures for the Private dictionary.
  355. % These must be defined without `bind',
  356. % for the sake of the DISKFONTS feature.
  357. 4 dict begin
  358.  /-! {string currentfile exch readhexstring pop} def
  359.  /-| {string currentfile exch readstring pop} def
  360.  /|- {readonly def} def
  361.  /| {readonly put} def
  362. currentdict end /encrypted_procs exch def
  363. 4 dict begin
  364.  /-! {string currentfile exch readhexstring pop
  365.    4330 exch dup .type1encrypt exch pop} def
  366.  /-| {string currentfile exch readstring pop
  367.    4330 exch dup .type1encrypt exch pop} def
  368.  /|- {readonly def} def
  369.  /| {readonly put} def
  370. currentdict end /unencrypted_procs exch def
  371.  
  372. % Construct an inverse dictionary of encodings.
  373. /encodingnames mark
  374.  StandardEncoding /StandardEncoding
  375.  ISOLatin1Encoding /ISOLatin1Encoding
  376.  SymbolEncoding /SymbolEncoding
  377.  DingbatsEncoding /DingbatsEncoding
  378.  /resourceforall where
  379.   { pop (*) { cvn dup findencoding exch } 100 string /Encoding resourceforall }
  380.  if
  381. .dicttomark def
  382.  
  383. % Invert the standard encodings.
  384. .knownEncodings length 256 mul dict begin
  385.   0 .knownEncodings
  386.    {  { currentdict 1 index known { pop } { 1 index def } ifelse
  387.     1 add
  388.       }
  389.      forall
  390.    }
  391.   forall pop
  392. currentdict end /inverseencodings exch def
  393.  
  394. /writefont        % <psfile> writefont - (writes the current font)
  395.  { /psfile exch def
  396.    /Font currentfont def
  397.    /FontInfo Font /FontInfo .knownget not { 0 dict } if def
  398.    /FontType Font /FontType get def
  399.    /hasPrivate Font /Private known def
  400.    /Private hasPrivate { Font /Private get } { 0 dict } ifelse def
  401.    /readproc binary_CharStrings { (-| ) } { (-! ) } ifelse def
  402.    /privateprocs
  403.      encrypt_CharStrings binary_tokens not and
  404.       { encrypted_procs } { unencrypted_procs } ifelse
  405.      def
  406.    /addlenIV false def
  407.    /changelenIV use_lenIV 0 lt
  408.     { 0 }
  409.     { use_lenIV Private /lenIV .knownget not
  410.        { 4 /addlenIV use_lenIV 4 ne def } if sub }
  411.    ifelse def
  412.    /minimize
  413.      smallest_output
  414.      FontType 1 eq and
  415.      Font /UniqueID known and
  416.    def
  417.    (%!FontType) ws FontType wtstring cvs ws (-1.0: ) ws
  418.      currentfont /FontName get wt
  419.      FontInfo /version .knownget not { (001.001) } if wl
  420.    FontInfo /CreationDate .knownget { (%%Creation Date: ) ws wl } if
  421.    FontInfo /VMusage .knownget
  422.     { (%%VMusage: ) ws dup wt wtstring cvs wl }
  423.    if
  424.    (systemdict begin) wl
  425.  
  426. % If we're going to use eexec, create the filters now.
  427.    /realpsfile psfile def
  428.    eexec_encrypt
  429.     { /eexecfilter psfile binary_CharStrings not
  430.        { pop /bxstring 35 string def
  431.       { pop dup length 0 ne
  432.          { realpsfile exch writehexstring realpsfile (\n) writestring }
  433.          { pop }
  434.         ifelse bxstring
  435.       }
  436.      /NullEncode filter dup /hexfilter exch def
  437.        }
  438.       if 55665 /eexecEncode filter def
  439.     }
  440.    if
  441.  
  442. % Turn on binary tokens if relevant.
  443.    binary_tokens { (currentobjectformat 1 setobjectformat) wl } if
  444.  
  445. % If the file has a UniqueID, write out a check against loading it twice.
  446.    minimize
  447.     { Font /FontName get wo
  448.       Font /UniqueID get wo
  449.       Private length addlenIV { 1 add } if wo
  450.       Font length 1 add wo        % +1 for FontFile
  451.       ( .checkexistingfont) wl
  452.     }
  453.     { Font /UniqueID known
  454.        { ({} FontDirectory) ws Font /FontName get dup wo ( known) wl
  455.      ( {) ws wo ( findfont dup /UniqueID known) wl
  456.      (    { dup /UniqueID get) ws Font /UniqueID get wo ( eq exch /FontType get 1 eq and }) wl
  457.      (    { pop false } ifelse) wl
  458.      (    { pop save /restore load } if) wl
  459.      ( } if) wl
  460.        }
  461.       if
  462.     }
  463.    ifelse
  464.  
  465. % If we are writing unencrypted CharStrings for a standard environment,
  466. % write out the encryption procedures.
  467.    privateprocs unencrypted_procs eq standard_only and
  468.     { (systemdict /.type1encrypt known) wl
  469.       ( { save /restore load } { { } } ifelse) wl
  470.       (userdict begin) wl
  471.       enc_dict { we } forall
  472.       (end exec) wl
  473.     }
  474.    if
  475.  
  476. % Write out the creation of the font dictionary and FontInfo.
  477.    minimize not
  478.     { Font length 1 add wo {dict begin} wol        % +1 for FontFile
  479.     }
  480.    if
  481.    (/FontInfo ) ws FontInfo wd {readonly def} wol
  482.  
  483. % Write out the other fixed entries in the font dictionary.
  484.    Font begin
  485.    Font
  486.     { minimize
  487.        { .minfontskipkeys 2 index known
  488.       { pop pop
  489.       }
  490.       { //.compactfontdefault 2 index .knownget
  491.          { 1 index valueeq { pop pop } { we } ifelse }
  492.          { we }
  493.         ifelse
  494.       }
  495.      ifelse
  496.        }
  497.        { .fontskipkeys 2 index known { pop pop } { we } ifelse
  498.        }
  499.       ifelse
  500.     } forall
  501.    /Encoding
  502.    encodingnames Encoding known
  503.    name_all_Encodings
  504.    Encoding StandardEncoding eq or
  505.    Encoding ISOLatin1Encoding eq or and
  506.     { encodingnames Encoding get cvx }
  507.     { Encoding }
  508.    ifelse
  509.    dup /StandardEncoding cvx eq minimize and
  510.     { pop pop }
  511.     { we }
  512.    ifelse
  513.  
  514. % Write the FDepVector, if any.
  515.    Font /FDepVector .knownget
  516.     { {/FDepVector [} wol
  517.        { /FontName get wo {findfont} wol () wl } forall
  518.       {] readonly def} wol
  519.     }
  520.    if
  521.  
  522. % Write out the Metrics, if any.
  523.    Font /Metrics .knownget
  524.     { (/Metrics ) ws wld {readonly def} wol
  525.     }
  526.    if
  527.    Font /Metrics2 .knownget
  528.     { (/Metrics2 ) ws wld {readonly def} wol
  529.     }
  530.    if
  531.  
  532. % Start the eexec-encrypted section, if applicable.
  533.   eexec_encrypt
  534.    { {currentdict currentfile eexec} wol () wl
  535.      /psfile eexecfilter store
  536.      (\000\000\000\000) ws {begin} wol
  537.    }
  538.   if
  539.  
  540. % Create and initialize the Private dictionary, if any.
  541.    hasPrivate
  542. {
  543.    Private
  544.    minimize
  545.     { begin {Private dup begin}
  546.     }
  547.     {  dup length privateprocs length add dict copy begin
  548.        privateprocs { readonly def } forall
  549.        /Private wo
  550.        currentdict length 1 add wo {dict dup begin}
  551.     }
  552.    ifelse wol () wl
  553.    currentdict
  554.     { 1 index minimize { .minprivateskipkeys } { .privateskipkeys } ifelse
  555.       exch known
  556.        { pop pop }
  557.        { 1 index /lenIV eq use_lenIV 0 ge and { pop use_lenIV } if we }
  558.       ifelse
  559.     } forall
  560.    addlenIV { /lenIV use_lenIV we } if
  561. }
  562. if
  563.  
  564. % Write the Subrs entries, if any.
  565.    currentdict /Subrs known
  566.     { (/Subrs[) wl
  567.       Subrs
  568.        { dup null ne
  569.       { wcs minimize not { () wl } if }
  570.       { pop /null cvx wo }
  571.      ifelse
  572.        } forall
  573.       {] dup {readonly pop} forall readonly def} wol () wl
  574.     }
  575.    if
  576.  
  577. % Wrap up the Private dictionary.
  578.    hasPrivate
  579.     { end            % Private
  580.       minimize
  581.        { {end readonly pop} }    % Private
  582.        { {end readonly def} }    % Private in font
  583.       ifelse wol
  584.     }
  585.    if
  586.  
  587. % Write the CharStrings entries.
  588. % Detect identical (eq) entries, which bdftops produces.
  589.    currentdict /CharStrings known
  590. {
  591.    /CharStrings wo CharStrings length wo
  592.    minimize
  593.     { encrypt_CharStrings not wo ( .readCharStrings) wl
  594.       CharStrings length dict
  595.       CharStrings
  596.        { exch inverseencodings 1 index .knownget not { dup } if wo
  597.         % Stack: vdict value key
  598.      3 copy pop .knownget { wo pop pop } { 3 copy put pop wcs } ifelse
  599.        } forall
  600.     }
  601.     { {dict dup Private begin begin} wol () wl
  602.       CharStrings length dict
  603.       CharStrings
  604.        { 2 index 1 index known
  605.       { exch wo 1 index exch get wo {load def} wol () wl
  606.       }
  607.       { 2 index 1 index 3 index put
  608.         exch wo wcs ( |-) wl
  609.       }
  610.      ifelse
  611.        } forall
  612.       {end end} wol
  613.     }
  614.    ifelse
  615.    pop
  616.     { readonly def }    % CharStrings in font
  617.    wol
  618. }
  619. if
  620.  
  621. % Terminate the output.
  622.    end            % Font
  623.    eexec_encrypt
  624.     { {end mark currentfile closefile} wol () wl
  625.       eexecfilter dup flushfile closefile    % psfile is eexecfilter
  626.       binary_CharStrings not { hexfilter dup flushfile closefile } if
  627.       /psfile realpsfile store
  628.       8
  629.        { (0000000000000000000000000000000000000000000000000000000000000000)
  630.          wl
  631.        }
  632.       repeat {cleartomark} wol
  633.     }
  634.    if
  635.     { FontName currentdict end definefont pop
  636.     }
  637.    wol
  638.    Font /UniqueID known { /exec cvx wo } if
  639.    binary_tokens { /setobjectformat cvx wo } if
  640.    ( end) wl        % systemdict
  641.  
  642.  } bind def
  643.  
  644. % ------ Other utilities ------ %
  645.  
  646. % Prune garbage characters and OtherSubrs out of the current font,
  647. % if the relevant dictionaries are writable.
  648. /prunefont
  649.  { currentfont /CharStrings get wcheck
  650.     { currentfont /CharStrings get dup [ exch
  651.        { pop dup (S????00?) .stringmatch not { pop } if
  652.        } forall
  653.       ] { 2 copy undef pop } forall pop
  654.     }
  655.    if
  656.  } bind def
  657.  
  658. end            % wrfont_dict
  659.  
  660. /writefont { wrfont_dict begin writefont end } def
  661.